/**
 ***********************************************************************************************************
 * Classes containing description about the underlying hardware
 ***********************************************************************************************************
 * @file RBD3D9SystemDesc.h
 ***********************************************************************************************************/

#ifndef __RBD3D9SYSTEMDESC_H__
#define __RBD3D9SYSTEMDESC_H__

#ifdef  HEADER_ONCE
#pragma HEADER_ONCE
#endif

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBD3D9SystemDesc.h)
#endif

/***********************************************************************************************************
 * Includes
 ***********************************************************************************************************/
#include "RBMain/RBRefObject.h"

/***********************************************************************************************************
 * Forward declarations
 ***********************************************************************************************************/

/***********************************************************************************************************
 * Classes
 ***********************************************************************************************************/

class RBD3D9DeviceDesc : public RBRefObject
{
public:
    RBD3D9DeviceDesc(IDirect3D9* pD3DObject, uint32 uiAdapter, D3DDEVTYPE d3dDevType, D3DFORMAT);

    const D3DCAPS9& GetCaps () const { return m_d3dCaps; }

private:
    D3DDEVTYPE  m_d3dDevType;
    D3DCAPS9    m_d3dCaps;

};

RBDeclareSmartPointer(RBD3D9DeviceDesc);

class RBD3D9AdapterDesc : public RBRefObject
{
    friend class RBD3D9DeviceDesc;
public:
    struct ModeDesc 
    {
        uint32 Width;
        uint32 Height;
        uint32 RefreshRate;
        D3DFORMAT Format;

        ModeDesc(uint32 Width=0, uint32 Height=0, uint32 RefreshRate=0, D3DFORMAT Format=D3DFMT_UNKNOWN) 
        {
            this->Width = Width;
            this->Height = Height;
            this->RefreshRate = RefreshRate;
            this->Format = Format;
        }

        bool operator==(const ModeDesc& rhs) const
        {
            return Width == rhs.Width && Height == rhs.Height && Format == rhs.Format;
        }

        bool operator!=(const ModeDesc& rhs) const
        {
            return !(*this == rhs);
        }

    };

                            RBD3D9AdapterDesc(IDirect3D9* pD3DObject, uint32 uiAdapter);
    virtual                ~RBD3D9AdapterDesc();

    RBD3D9DeviceDesc*        GetHALDeviceDesc();

    ModeDesc*               GetClosestModeDesc();

private:
    uint32                  m_uiAdapter;
    D3DADAPTER_IDENTIFIER9  m_d3dAdapterIdentifier;
    RBD3D9DeviceDesc*        m_pHALDeviceDesc;
    std::vector<ModeDesc>   m_aModes;
};

RBDeclareSmartPointer(RBD3D9AdapterDesc);

class RBD3D9SystemDesc : public RBRefObject
{
    friend class RBD3D9DeviceDesc;
    friend class RBD3D9AdapterDesc;
public:
                        RBD3D9SystemDesc     (IDirect3D9* pD3DObject);
    virtual            ~RBD3D9SystemDesc     ();

    RBD3D9AdapterDesc*   GetAdapterDesc      (uint32 uiAdapter) { return m_aAdaptersDesc[uiAdapter]; }

private:
    std::vector<RBD3D9AdapterDesc*> m_aAdaptersDesc;
    static const uint32            ms_uiNbPixelFormats = 6;
    static const D3DFORMAT         ms_aPixelFormats[ms_uiNbPixelFormats];
};


RBDeclareSmartPointer(RBD3D9SystemDesc);

/***********************************************************************************************************/

#endif // __RBD3D9SYSTEMDESC_H__